<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <currency-input
            label="Price"
            v-model="price"
    ></currency-input>
    <currency-input
            label="Shipping"
            v-model="shipping"
    ></currency-input>
    <currency-input
            label="Handling"
            v-model="handling"
    ></currency-input>
    <currency-input
            label="Discount"
            v-model="discount"
    ></currency-input>

    <p>Total: ${{ total }}</p>
</div>
<script src="../js/vue.min.js"></script>
<script>
    var currencyValidator = {
        format: function (number) {
            return (Math.trunc(number * 100) / 100).toFixed(2)
        },
        parse: function (newString, oldNumber) {
            var CleanParse = function (value) {
                return { value: value }
            }
            var CurrencyWarning = function (warning, value) {
                return {
                    warning: warning,
                    value: value,
                    attempt: newString
                }
            }
            var NotAValidDollarAmountWarning = function (value) {
                return new CurrencyWarning(newString + ' is not a valid dollar amount', value)
            }
            var AutomaticConversionWarning = function (value) {
                return new CurrencyWarning(newString + ' was automatically converted to ' + value, value)
            }

            var newNumber = Number(newString)
            var indexOfDot = newString.indexOf('.')
            var indexOfE = newString.indexOf('e')

            if (isNaN(newNumber)) {
                if (
                        indexOfDot === -1 &&
                        indexOfE > 0 &&
                        indexOfE === newString.length - 1 &&
                        Number(newString.slice(0, indexOfE)) !== 0
                ) {
                    return new CleanParse(oldNumber)
                } else {
                    return new NotAValidDollarAmountWarning(oldNumber)
                }
            }

            var newCurrencyString = currencyValidator.format(newNumber)
            var newCurrencyNumber = Number(newCurrencyString)

            if (newCurrencyNumber === newNumber) {
                if (indexOfE !== -1 && indexOfE === newString.length - 2) {
                    return new AutomaticConversionWarning(newNumber)
                } else {
                    return new CleanParse(newNumber)
                }
            } else {
                return new NotAValidDollarAmountWarning(
                        newNumber > newCurrencyNumber
                                ? newCurrencyNumber
                                : oldNumber
                )
            }
        }
    }
</script>
<script>
    Vue.component('currency-input', {
        template: '\
    <div>\
      <label v-if="label">{{ label }}</label>\
      $\
      <input\
        ref="input"\
        v-bind:value="value"\
        v-on:input="updateValue($event.target.value)"\
        v-on:focus="selectAll"\
        v-on:blur="formatValue"\
      >\
    </div>\
  ',
        props: {
            value: {
                type: Number,
                default: 0
            },
            label: {
                type: String,
                default: ''
            }
        },
        mounted: function () {
            this.formatValue()
        },
        methods: {
            updateValue: function (value) {
                var result = currencyValidator.parse(value, this.value)
                if (result.warning) {
                    this.$refs.input.value = result.value
                }
                this.$emit('input', result.value)
            },
            formatValue: function () {
                this.$refs.input.value = currencyValidator.format(this.value)
            },
            selectAll: function (event) {
                // Workaround for Safari bug
                // http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome
                setTimeout(function () {
                    event.target.select()
                }, 0)
            }
        }
    })

    new Vue({
        el: '#app',
        data: {
            price: 0,
            shipping: 0,
            handling: 0,
            discount: 0
        },
        computed: {
            total: function () {
                return ((
                        this.price * 100 +
                        this.shipping * 100 +
                        this.handling * 100 -
                        this.discount * 100
                ) / 100).toFixed(2)
            }
        }
    })
</script>
</body>
</html>